package util.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class CryptoUtil {
	
	private static final String ALGO_MD5 = "MD5";
	private static final String ALGO_HMAC_MD5 = "HmacMD5";
	private static final String ALGO_SHA1 = "SHA";
	
	/**
	 * SHA1加密
	 * @param str
	 * @return
	 */
	public static String getSha1(String str) {
		byte[] bytes = str.getBytes();
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance(ALGO_SHA1);
			md.update(bytes);
		} catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		}
		return bytes2Hex(md.digest());
	}
	
	/**
	 * MD5加密(加密串 长度32位)
	 * 
	 * @param str 加密的源字符串
	 *            
	 * @return
	 */
	public static String getMD5(String str) {
		MessageDigest md = null;
		String md5Str = null;
		
		byte[] strBytes = str.getBytes();
		try {
			md = MessageDigest.getInstance(ALGO_MD5);
			md.update(strBytes);
			md5Str = bytes2Hex(md.digest());
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalStateException("系统不支持的MD5算法！");
		}
		return md5Str;
	}
	
	
	/**
	 * 文件MD5的值
	 * 
	 * 
	 * @param file
	 * @return
	 */
	public static String getMD5(File file) {
		MessageDigest md = null;
		String md5Str = null;

		FileInputStream fileInputStream = null;
		try {

			fileInputStream = new FileInputStream(file);
			MappedByteBuffer byteBuffer = fileInputStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0,
					file.length());

			md = MessageDigest.getInstance(ALGO_MD5);
			md.update(byteBuffer);
			md5Str = bytes2Hex(md.digest());
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalStateException("系统不支持的MD5算法！");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new IllegalStateException("FileNotFoundException");
		} catch (IOException e) {
			e.printStackTrace();
			throw new IllegalStateException("IOException");
		} finally {

			try {
				if (fileInputStream != null) {
					fileInputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return md5Str;
	}
	
	/**
	 * MD5加密(加密串 长度32位)
	 * @param strSrc
	 * @param charset
	 * @return
	 */
	public static String getMD5(String strSrc, String charset) {
		MessageDigest md = null;
		String strDes = null;
		byte[] bt=null;
        try {
	        bt = strSrc.getBytes(charset);
        } catch (UnsupportedEncodingException e1) {
        }
		try {
			md = MessageDigest.getInstance(ALGO_MD5);
			md.update(bt);
			strDes = bytes2Hex(md.digest());
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalStateException("系统不支持的MD5算法！");
		}
		return strDes;
	}
	
	/**
	 * HMAC_MD5加密
	 * 
	 * @param key
	 * @param str
	 * 
	 * @return
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeyException 
	 */
	public static String getHmacMD5(String key, String str) throws NoSuchAlgorithmException, InvalidKeyException {
		SecretKeySpec sk = new SecretKeySpec(key.getBytes(), ALGO_HMAC_MD5);
		byte[] strBytes = str.getBytes();
		Mac mac;
		try {
			mac = Mac.getInstance(ALGO_HMAC_MD5);
			mac.init(sk);
		} catch (NoSuchAlgorithmException e) {
			throw new NoSuchAlgorithmException(e);
		} catch (InvalidKeyException e) {
			throw new InvalidKeyException(e);
		}
		
		return bytes2Hex(mac.doFinal(strBytes));
	}
	
	

	/**
	 * 将字节数组转为HEX字符串(16进制串)
	 * 
	 * @param strBytes 要转换的字节数组
	 *            
	 * @return 
	 */
	private static String bytes2Hex(byte[] strBytes) {
		String str = "";
		String tmp = null;
		for (int i = 0; i < strBytes.length; i++) {
			tmp = (Integer.toHexString(strBytes[i] & 0xFF));
			if (tmp.length() == 1) {
				str += "0";
			}
			str += tmp;
		}
		return str;
	}

}

